<?php
/* 
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 * Description of actions
 *
 * @author stephane
 */
class jckLocationToolsActions extends sfActions
{
  //put your code here
  public function  executeGetAddresses($request)
  {
    
    $this->errors = array();
    $this->warnings = array();
    $this->addressLocations = array();
    $this->debug = "";

    $this->warnings[] = 'simple test';
    $requestApi = false;
    
    if( ! $input = trim($request->getParameter('term')) ){
      $this->errors = $this->errors[] = 'address parameter is required !';
    }

    else {

      // Récupération du code postale
      $zipCode = (preg_match('/(\d+)/', $input, $match)?$match[1]:null);

      // Récupération de la ville
      $city = (preg_match('/(\D+)/', $input, $match)?strtoupper(trim($match[1])):null);

      //if( strlen($zipCode) > 3 && strlen($city) > 2 ){
      if( strlen($zipCode) > 3 && strlen($city) > 2 || strlen($city) > 5){
        // Try request API
        $requestApi = true;
        $this->logMessage("API WHILE REQUESTED");
      }

      $this->addressLocations = AddressLocationTable::getLikeZipAndCity($zipCode, $city);
      $this->logMessage(count($this->addressLocations)." result(s)");
      if( count($this->addressLocations) == 0 ){

        if( $requestApi ){
          // API
          $this->logMessage("API REQUEST");
          $xml =  sprintf('http://maps.googleapis.com/maps/api/geocode/xml?address=%s&region=fr&sensor=false', urlencode($zipCode.' '.$city));
          $this->logMessage("API REQUEST : $xml");
          $datas = simplexml_load_file($xml);

          if( $datas->status == 'OK' ){
            $results = $datas->children();
            foreach( $results as $result ){
              if( $result->getName() == 'result' ){

               

                if( $result->type[0] == 'locality') {
                  $newCity = new AddressLocation(null, true);
                  foreach($result->children() as $cityInfos){

                    

                    switch( $cityInfos->type[0] ) {
                      // Département
                      case 'locality' :
                        $this->debug .= (string)$cityInfos->long_name;
                        $newCity->setCity((string)$cityInfos->long_name);
                        //
                        break;

                      // Département
                      case 'administrative_area_level_2' :
                        //
                        break;

                      // Région
                      case 'administrative_area_level_1' :
                        //
                        break;

                      // Pays
                      case 'country' :
                        $newCity->setCountry((string)$cityInfos->short_name);
                        break;

                      // Code postale
                      case 'postal_code' :

                        $newCity->setZipCode((string)$cityInfos->long_name[0]);
                        break;

                    }

                    

                  }
                  $newCity->setLat((float)$result->geometry->location->lat);
                  $newCity->setLng((float)$result->geometry->location->lng);
                  if( $newCity->isValid() ){
                    $newCity->save();
                  } else {
                    $this->warnings[] = 'Enable to memorize new city';
                  }
                  $this->addressLocations[] = $newCity;

                } else {
                  $this->debug = $result;
                }
              }
            }
          }
          //
          
        }

        else {
          $errors[] = sprintf("Location not found for %s, %s", $zipCode, $city);
        }
      }
      //$request->setR
      //$this->renderPartial('jckLocationTools/adresses');
    }
  }

  public function  executeGetAddressByCity($request) {
    return $this->renderText('ville');
  }

  public function  executeGetAddressByZipCode($request) {
    return $this->renderText('ZIP');
  }


/*
  public function executeUpdateCommuneListe(sfWebRequest $request)
  {
    
    $dep = $request->getParameter('dep');
    $this->communesURL = sprintf('http://fr.wikipedia.org/wiki/%s', $dep);
    $this->communes = array();

    $loadCom = new DOMDocument();

    if( $loadCom->loadHTMLFile($this->communesURL) ){
      $lignes = $loadCom->getElementsByTagName('tr');

      $communeField   = null;
      $inseeField     = null;
      $cpField        = null;
      $enteteOk       = false;

      foreach ($lignes as $ligne){
        // -------------------------------------------------------------------
        // En tête
        if( !$enteteOk ) {
          $entetes = $ligne->getElementsByTagName('th');
          if( $entetes->length < 3 ) continue;

          foreach ( $entetes as $key=>$entete ){

            switch( trim($entete->nodeValue) ){
              case 'Commune' :
                $communeField = $key;
                break;
              case 'Code INSEE' :
                $inseeField = $key;
                break;
              case 'Code Postal' :
                $cpField = $key;
                break;

            }
          }
          $enteteOk = true;
          continue;
        }

        // -------------------------------------------------------------------
        // Données
        $lignes = $ligne->getElementsByTagName('td');
        if( $lignes->length < 3 ) continue;

        $commune  = $lignes->item($communeField)->nodeValue;
        $insee    = $lignes->item($inseeField)->nodeValue;
        $cp       = $lignes->item($cpField)->nodeValue;

        if(strlen($insee) == 5 && is_numeric($insee)){
          $newCommune = new AddressLocation(null, true);
          $newCommune->setCity(trim($commune));
          $newCommune->setZipCode(trim($cp));
          $newCommune->setInsee($insee);
          $this->communes[] = $newCommune;
        }

        // Données autres
        else {
          continue;
        }
      }
    }

    else {
      $this->error = $communes.' incorrecte';
    }
  }
 * */

  public function executeSynchronizeCommune( sfWebRequest $request )
  {
    // Récupération des données
    $this->forward404Unless($communeName  = $request->getParameter('commune'), 'Vous devez entrer une commune');
    $this->forward404Unless($communeInsee = $request->getParameter('insee'), 'N° INSEE manquant');
    $this->forward404Unless($communeCp    = $request->getParameter('cp'), 'Code postal manquant');
    
    $commune = AddressLocationTable::getCommuneByInsee($communeInsee);
    
    // Mise à jour d'une commune existante
    if( $commune ){
      /****
      if( $commune->getLat() == 0 && $commune->getLng() == 0 ){
        $this->logMessage(' - GL UPDATE for'.$commune.'.');
        try {
          $this->updateLatLngCommune($commune);
          return $this->renderText('OK');
        } catch (jckLocationGMException $e ){
          return $this->renderText('GM_ERROR');
        } catch ( Exception $e ) {
          $this->forward404($e->getMessage().' - '.$e->getCode());
        }
      }
      /****/
      return $this->renderText('UNCHANGE');
    } 
    
    else {

      $newCommune = new AddressLocation(null, true);
      $newCommune->setCity($communeName);
      $newCommune->setInsee($communeInsee);
      $newCommune->setZipCode($communeCp);
      try{
        $newCommune->save();
        return $this->renderText('OK');
      } catch ( Exception $e ){
        return $this->renderText('ERROR : ' + $e->getMessage());
      }

      // Récupération de la géolocalisation
      /****
      try {
        if( null !== $latLng = $this->getLatLng($communeCp, $communeName) ){
          $newCommune->setLat($latLng['lat']);
          $newCommune->setLng($latLng['lng']);
          $newCommune->save();
        }
      } 
      // Error Google GeoCode
      catch ( jckLocationGMException $e ) {
        return $this->renderText('GM_EXCEPTION');
      }

      // Error Requète
      catch ( Exception $e ){
        return $this->renderText('ERROR');
      }
      /****/
      return $this->renderText('OK');
    }
  }

  protected function getLatLng( $cp, $city)
  {
    $geometry = null;
    $xml =  sprintf('http://maps.googleapis.com/maps/api/geocode/xml?address=%s&region=fr&sensor=false', urlencode($cp.' '.$city));
    $this->logMessage('request Google : '.$xml.'.');
    $datas = simplexml_load_file($xml);

    $status = $datas->status;

    if( $status == 'OK' ){
      $lat = (float)$datas->result->geometry->location->lat;
      $lng = (float)$datas->result->geometry->location->lng;
      return array('lat'=>$lat, 'lng'=>$lng);
    } 
    
    else if($status == 'OVER_QUERY_LIMIT') {
      throw new jckLocationException('Google GeoCode service over query');
    }
  }

  protected function updateLatLngCommune( AddressLocation $commune )
  {
    $geometry = $this->getLatLng($commune->getZipCode(), $commune->getCity());

    if( $geometry !== null ){
      $commune->setLat($geometry['lat']);
      $commune->setLng($geometry['lng']);
      try {
        $commune->save();
        return $commune;
      } catch ( Exception $e ){
        throw new jckLocationException('Impossible de géolocaliser %s', $commune);
      }
    }
  }

  public function executeSynchronize( sfWebRequest $request )
  {
   

    $this->communesConnues = AddressLocationTable::getList();
    $this->communesListe = array();

    


    $source = 'http://fr.wikipedia.org/wiki/Listes_des_communes_de_France';
    $domDocument = new DOMDocument();
    $domDocument->loadHTMLfile($source);

    $liens = $domDocument->getElementsByTagName('a');

    foreach( $liens as $lien ){
      $title = $lien->getAttribute('title');
      $depCompleted = false;
      if(preg_match('/Liste des communes (de|des|du|d\'|de la) (.+)/', $title, $match)){
        $communesURL = 'http://fr.wikipedia.org' . $lien->getAttribute('href');
        $this->communesListe[] = array(
            'url'   => $communesURL,
            'title' => $title
        );
        // $this->communes = array_merge($this->communes, $this->getListeCommunes($communesURL));
      } else {
        continue;
      }
    }
  }
  /**
   *
   * @param sfWebRequest $request
   * @return <type>
   */
  public function executeListeCommuneURL( sfWebRequest $request )
  {

    $this->communes = $this->getListeCommunes($request->getParameter('url'));
    return $this->renderPartial('communeListe');
  }

  protected function getListeCommunes( $url )
  {
    $this->logMessage('parsing : '. $url);

    $communes = array();

    $loadCom = new DOMDocument();

    $opts = array(
      'http'=>array(
        'method'=>"GET",
        'header'=>"Accept-language: en\r\n" .
                    "User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1\r\n" .
                    "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" .
                    "Accept-Language: fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3\r\n" .
                    /*"Accept-Encoding: gzip, deflate\r\n" .
                    "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n" .
                    "Keep-Alive: 115\r\n" .
                    "Connection: keep-alive\r\n"*/
                    ""
      )
    );
    $context = stream_context_create($opts);
    $file_content = file_get_contents($url, false, $context);


    if( $loadCom->loadHTML($file_content) ){
      /****/
      $lignes = $loadCom->getElementsByTagName('tr');

      $communeField   = null;
      $inseeField     = null;
      $cpField        = null;
      $enteteOk       = false;

      foreach ($lignes as $ligne){
        // -------------------------------------------------------------------
        // En tête
        if( !$enteteOk ) {
          $entetes = $ligne->getElementsByTagName('th');
          if( $entetes->length < 3 ) continue;

          foreach ( $entetes as $key=>$entete ){
            $this->logMessage($entete->nodeValue);
            
            if( preg_match('/(P|p)ostal/', $entete->nodeValue) ){
              $cpField = $key;
              continue;
            }

            if( preg_match('/(Insee|INSEE)/', $entete->nodeValue) ){
              $inseeField = $key;
              continue;
            }

            switch( strip_tags(trim($entete->nodeValue)) ){
              case 'Commune' :
                $communeField = $key;
                break;
              case 'Code INSEE' :
              case 'Code Insee' :
                $inseeField = $key;
                break;
              case 'Code Postal' :
                $cpField = $key;
                break;

            }
          }
          $enteteOk = true;
          // throw new Exception($communeField.' // ' . $inseeField . ' // ' . $cpField);
          continue;
        }

        // -------------------------------------------------------------------
        // Données
        $lignes = $ligne->getElementsByTagName('td');
        if( $lignes->length < 3 ) continue;

        $commune  = $lignes->item($communeField)->nodeValue;
       // str_replace($search, $replace, $subject)
        $insee = strval($lignes->item($inseeField)->nodeValue)."";
        $insee = preg_replace("/&#?[a-z0-9]{2,8};/","", $insee);
        //throw new Exception($insee);
        $insee    = str_replace(' ', '', trim($lignes->item($inseeField)->nodeValue));
        $cp       = str_replace(' ', '', trim($lignes->item($cpField)->nodeValue));

       // throw new Exception(str_replace('&nbsp;', '', $insee));
        // preg_match('/Liste des communes (de|des|du|d\'|de la) (.+)/', $title, $match)
        if( preg_match('/[0-9][0-9AB]{1}[0-9]{3}/', $insee) ){
        //if(strlen($insee) == 5 && is_numeric($insee)){
          $newCommune = new AddressLocation(null, true);
          $newCommune->setCity(trim($commune));
          $newCommune->setZipCode(trim($cp));
          $newCommune->setInsee($insee);
          $communes[] = $newCommune;
        }



        // Données autres
        else {

          //throw new Exception('INSEE '.$insee.'dont match in ' . $url);
          continue;
        }
      }
       /****/

    }

    else {
      throw new Exception('Erreur de chargement de la source '.$url);
      return array();
    }

    return $communes;
  }
    /****/
  
}
?>